﻿using System;
using System.Text;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.XLANGs.BaseTypes;
using Microsoft.BizTalk.Component.Interop;
using log4net;
using System.Reflection;
using AppFx.BizTalk.Diagnostics;

namespace AppFx.BizTalk.PipelineComponents
{
    /// <summary>
    /// Base PLC with reusable features for normal pipeline component development
    /// </summary>
    public abstract class BaseCustomPipelineComponent : Microsoft.BizTalk.Component.Interop.IBaseComponent
    {
        private static readonly ILog Log = LogFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private readonly string _name;
        private readonly string _version;
        private readonly string _description;

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="name"></param>
        /// <param name="componentType"></param>
        /// <param name="description"></param>
        protected BaseCustomPipelineComponent(string name, Type componentType, string description)
        {            
            _name = name;
            _version = componentType.Assembly.GetName().Version.ToString();
            _description = description;
        }

        #region IBaseComponent Members
        /// <summary>
        /// The PLC description
        /// </summary>
        public string Description
        {
            get { return _description; }
        }
        /// <summary>
        /// Return the PLC name
        /// </summary>
        public string Name
        {
            get { return _name; }
        }
        /// <summary>
        /// The PLC version number
        /// </summary>
        public string Version
        {
            get { return _version; }
        }
        #endregion

        #region Context Properties
        /// <summary>
        /// Reads a context property
        /// </summary>
        /// <param name="context"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        protected object ReadContextProperty(IBaseMessageContext context, MessageContextPropertyBase property)
        {
            return context.Read(property.Name.Name, property.Name.Namespace);
        }
        /// <summary>
        /// Reads a property as a string
        /// </summary>
        /// <param name="context"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        protected string ReadContextPropertyAsString(IBaseMessageContext context, MessageContextPropertyBase property)
        {
            return (string)context.Read(property.Name.Name, property.Name.Namespace);
        }
        /// <summary>
        /// Promotes a property
        /// </summary>
        /// <param name="context"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        protected void PromoteContextProperty(IBaseMessageContext context, MessageContextPropertyBase property, object val)
        {
            context.Promote(property.Name.Name, property.Name.Namespace, val);
        }
        /// <summary>
        /// Promotes a property
        /// </summary>
        /// <param name="context"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        protected void WriteContextProperty(IBaseMessageContext context, MessageContextPropertyBase property, object val)
        {
            context.Write(property.Name.Name, property.Name.Namespace, val);
        }
        /// <summary>
        /// Promotes a property
        /// </summary>
        /// <param name="context"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        protected void WriteAndPromoteContextProperty(IBaseMessageContext context, MessageContextPropertyBase property, object val)
        {
            context.Write(property.Name.Name, property.Name.Namespace, val);
            context.Promote(property.Name.Name, property.Name.Namespace, val);
        }
        #endregion

        #region Message Part Properties
        /// <summary>
        /// Reads a message part property
        /// </summary>
        /// <param name="part"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        protected object ReadPartProperty(IBaseMessagePart part, MessageContextPropertyBase property)
        {
            return part.PartProperties.Read(property.Name.Name, property.Name.Namespace);
        }
        /// <summary>
        /// Reads a message part property as a string
        /// </summary>
        /// <param name="part"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        protected string ReadPartPropertyAsString(IBaseMessagePart part, PartContextPropertyBase property)
        {
            return (string)part.PartProperties.Read(property.Name.Name, property.Name.Namespace);
        }
        /// <summary>
        /// Promotes a property
        /// </summary>
        /// <param name="part"></param>
        /// <param name="property"></param>
        /// <param name="val"></param>
        protected void WritePartProperty(IBaseMessagePart part, PartContextPropertyBase property, object val)
        {
            part.PartProperties.Write(property.Name.Name, property.Name.Namespace, val);
        }
        #endregion                

        #region PropertyBag
        /// <summary>
        /// Reads a value from the property bag if it exists and casts to int
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        protected int GetPropertyBagAsInt(IPropertyBag pb, string propertyName)
        {
            object temp = PropertyBagHelper.Read(pb, propertyName);
            return temp != null ? 0 : Convert.ToInt32(temp);
        }

        /// <summary>
        /// Reads a value from the property bag if it exists and casts to bool
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        protected bool GetPropertyBagAsBool(IPropertyBag pb, string propertyName)
        {
            var val = false;
            object temp = PropertyBagHelper.Read(pb, propertyName);

            if (temp is bool)
            {
                return (bool)temp;
            }
            else
            {
                var parses = bool.TryParse(Convert.ToString(temp), out val);
                if (parses)
                    return val;
                else
                {
                    Log.Debug(string.Format("ReadPropertyBagAsBool - {0} does not convert to a bool value", propertyName));
                    return false;
                }
            }
        }

        /// <summary>
        /// Reads a value from the property bag if it exists
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        protected void ReadPropertyBag(IPropertyBag pb, string propertyName, ref object propertyValue)
        {
            object temp = PropertyBagHelper.Read(pb, propertyName);
            if (temp != null)
                propertyValue = temp;
        }
        /// <summary>
        /// Reads a value from the property bag if it exists
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        protected void ReadPropertyBag(IPropertyBag pb, string propertyName, ref string propertyValue)
        {
            string temp = (string)PropertyBagHelper.Read(pb, propertyName);
            if (!string.IsNullOrEmpty(temp))
                propertyValue = temp;
        }
        /// <summary>
        /// Reads a value from the property bag if it exists
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        protected void ReadPropertyBagAsBool(IPropertyBag pb, string propertyName, ref bool propertyValue)
        {
            string temp = (string)PropertyBagHelper.Read(pb, propertyName);
            if (!string.IsNullOrEmpty(temp))
            {
                propertyValue = Convert.ToBoolean(temp);
            }
        }
        /// <summary>
        /// Reads a value from the property bag if it exists
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        protected void ReadPropertyBagAsInt(IPropertyBag pb, string propertyName, ref int propertyValue)
        {
            var temp = PropertyBagHelper.Read(pb, propertyName);
            if(temp is int)
            {
                var tempInt = Convert.ToInt32(temp);
                if (tempInt != 0)
                    propertyValue = tempInt;
            }
            if (temp is string)
            {
                var tempString = Convert.ToString(temp);
                if (!string.IsNullOrEmpty(tempString))
                {
                    propertyValue = Convert.ToInt32(temp);
                }
            }
        }
        /// <summary>
        /// Writes an item to the property bag
        /// </summary>
        /// <param name="pb"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        protected void WritePropertyBag(IPropertyBag pb, string propertyName, object propertyValue)
        {
            if (propertyValue != null)
                PropertyBagHelper.Write(pb, propertyName, propertyValue);
        }
        #endregion
    }
}

